<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2018 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: 小夏 < 449134904@qq.com>
// | Date: 2019/03/15
// | Time:上午 10:26
// | 用于网页微信登录，扫码或微信在线自动登录
// +----------------------------------------------------------------------
namespace plugins\xiongyi\controller;

use cmf\controller\PluginBaseController;
use plugins\xiongyi\lib\WechatOauth2;
//use think\Db;
use think\facade\Db;
use plugins\xiongyi\lib\User;
use think\exception\HttpException;

class WechatController extends PluginBaseController
{
    /**
     * 微信登录链接
     * https://f.kjdll.cn:9999/plugin/xiongyi/wechat/login
     * @return \think\response\Redirect
     * @throws \Exception
     */
    public function login()
    {
        $wechatOauth2 = new WechatOauth2();
        $config       = $this->getPlugin()->getConfig();
        $wechatOauth2->setAppKey($config['app_id']);
        $wechatOauth2->setAppSecret($config['app_secret']);
        //$url = cmf_plugin_url('WechatLogin://wechat/callback', [], true);
        $url = "https://f.kjdll.cn:9999/plugin/xiongyi/wechat/callback";        //回调地址，不须要url_encode
        //$url = "https%3A%2F%2Ff.kjdll.cn%3A9999%2Fplugin%2Fwechat_login%2Fwechat%2Fcallback";
        $wechatOauth2->setCallback($url);

        return redirect($wechatOauth2->getRequestCodeURL());
    }

    /**
     * 原方法，没有用，第三方登录授权回调地址
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     * @throws \Exception
     */
    public function callback1()
    {
        //var_dump($this->request->param());
        /**
         * { ["code"]=> string(32) "031ag00w3gJMv43klm1w3p9iGK0ag00K" 
         * ["state"]=> string(5) "STATE" 
         * ["_plugin"]=> string(12) "wechat_login" 
         * ["_controller"]=> string(6) "wechat" 
         * ["_action"]=> string(8) "callback" } 
         */

        $code = $this->request->param('code');
        if (empty($code)) {
            $this->error('参数不正确');
        }
        $wechatOauth2 = new WechatOauth2();
        $config       = $this->getPlugin()->getConfig();
        $wechatOauth2->setAppKey($config['app_id']);
        $wechatOauth2->setAppSecret($config['app_secret']);
        //var_dump("appid");
        //var_dump($config['app_id']);
        //var_dump("app_secret");
        //var_dump($config['app_secret']);
        $token = $wechatOauth2->getAccessToken($code);
        //var_dump($token);
        //获取当前登录用户信息
        if (is_array($token)) {

            $data = $wechatOauth2->call('sns/userinfo');

            //var_dump($data);
            /**
             * array(10) { 
             * ["openid"]=> string(28) "ocs7O67mv5obM2xjY0F3Xzv26XtA" 
             * ["nickname"]=> string(12) "夕阳余晖" 
             * ["sex"]=> int(0) ["language"]=> string(0) "" 
             * ["city"]=> string(0) "" 
             * ["province"]=> string(0) "" 
             * ["country"]=> string(0) "" 
             * ["headimgurl"]=> string(152) "https://thirdwx.qlogo.cn/mmopen/vi_32/D9hhtg7QVjfHAgRvdk59TfbscOXEVgkQu1v4reLZpE3JQEcq2DbPJqyiakjd8a7R4w2fShAFNBkDzL6qYMxWpF5L15Y4ia7MT5pDV1eEqeMiag/132" 
             * ["privilege"]=> array(0) { } 
             * ["unionid"]=> string(28) "opKXO61L5ZYgdvwEoOiw35bCIYCs" }    ////同一个开放平台添加的web页和小程序，获得的unionid是一样的
             */

            $userInfo = [
                'app_id'        => $config['app_id'],       //传入，用于识别是哪个程序
                'third_party' => 'wechat',
                'nickname'    => $data['nickname'],
                'avatar'      => $data['headimgurl'],
                'union_id'    => $data['unionid'],          //新增，用于微信WEB页登录 与 微信小程序登录 识别同一个用户
            ];

            $sessionOauthBang = session('oauth_bang');
            if (!empty($sessionOauthBang)) {
                //$this->_bang_handle($userInfo, 'wechat', $token);
                $this->loginHandle1($userInfo, 'wechat', $token);
            } else {
                $this->loginHandle1($userInfo, 'wechat', $token);
            }
        } else {
            $this->success('登录失败1！', $this->_getLoginRedirect());
        }
    }

    /**
     * 原方法，没有用，处理第三方登陆
     * @param        $userInfo
     * @param        $type
     * @param  array $token
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    private function loginHandle1($userInfo, $type, $token)
    {
        //$findThirdPartyUser = Db::name('third_party_user')->where(["third_party" => $type, "openid" => $token['openid']])->find();
        //不使用openid，因为同一个开放平台要兼容微信web登录和小程序登录，使用unionid识别即可
        $findThirdPartyUser = Db::name('third_party_user')->where(["union_id" => $userInfo['union_id']])->find();

        $needRegister       = true;
        if ($findThirdPartyUser) {
            $findUser = Db::name('user')->where(["id" => $findThirdPartyUser['user_id']])->find();
            if ($findUser) {
                $needRegister = false;
                if ($findUser['user_status'] == '0') {
                    $this->error('您已经被列入黑名单，请联系网站管理员！');
                } else {
                    if (!empty($findUser['more'])) $findUser['more'] = json_decode($findUser['more'], true);
                    //session('user', $findUser); //user是前台用户的
                    $this->_pSession($findUser["id"], $findUser["user_login"]);      //写入后台管理员session

                    $token = cmf_generate_user_token($findUser["id"], 'web');
                    if (!empty($token)) {
                        session('token', $token);
                    }

                    //判断用户是否有role和zzjg
                    //$ups = new UserPublicService;
                    $ups = new User();
                    $b = $ups->checkUserRoleAndZzjg($findUser['id']);
                    if (!$b) $this->success("登陆成功", $this->_getLoginRedirect());
                    $this->success("绑定角色和组织机构页", "/plugin/xiongyi/index/userbind");
                }
            } else {
                $needRegister = true;
            }
        }
        if ($needRegister) {
            //本地用户中创建对应一条数据
            $newUserData = [
                'user_nickname'   => $userInfo['nickname'],
                'avatar'          => $userInfo['avatar'],
                'last_login_time' => time(),
                'last_login_ip'   => get_client_ip(0, true),
                'create_time'     => time(),
                'user_status'     => '1',
                "user_type"       => '1',   //1-admin，2-会员
            ];

            Db::startTrans();
            $result = true;
            try {
                $newUserId = Db::name('user')->insertGetId($newUserData);
                if ($newUserId) {
                    //第三方用户表中创建数据
                    $newThirdPartyUserData = [
                        'user_id'         => $newUserId,
                        'last_login_time' => time(),
                        'expire_time'     => intval(time() + $token['expires_in']),
                        'create_time'     => time(),
                        'login_times'     => 1,
                        'status'          => 1,
                        'nickname'        => $userInfo['nickname'],
                        'third_party'     => $type,
                        'app_id'          => $userInfo['app_id'],
                        'last_login_ip'   => get_client_ip(0, true),
                        'access_token'    => $token['access_token'],
                        'openid'          => $token['openid'],
                        'union_id'         => $userInfo['union_id'],     //WEB和小程序绑定开放平台后，同一个微信用户union_id是一样的
                    ];

                    Db::name('third_party_user')->insert($newThirdPartyUserData);
                    $newUserData = Db::name('user')->where('id', $newUserId)->find();

                    //session('user', $newUserData);      //user是前台用户的
                    $this->_pSession($newUserData["id"], $newUserData["user_login"]);      //写入后台管理员session

                } else {
                    $result = false;
                }
                Db::commit();
            } catch (\Exception $e) {
                //var_dump($e);
                return;
                $result = false;
                Db::rollback();
            }
            if ($result) {
                $this->success("新微信用户，绑定角色和组织机构页", "/plugin/xiongyi/index/userbind");
                //$this->success("登陆成功", $this->_getLoginRedirect());
            } else {
                $this->error("登陆失败2！", $this->_getLoginRedirect());
            }
        }
    }

    /**
     * 第三方登录授权回调地址
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     * @throws \Exception
     */
    public function callback()
    {
        //var_dump($this->request->param());
        /**
         * { ["code"]=> string(32) "031ag00w3gJMv43klm1w3p9iGK0ag00K" 
         * ["state"]=> string(5) "STATE" 
         * ["_plugin"]=> string(12) "wechat_login" 
         * ["_controller"]=> string(6) "wechat" 
         * ["_action"]=> string(8) "callback" } 
         */

        $code = $this->request->param('code');
        if (empty($code)) {
            $this->error('参数不正确');
        }
        $wechatOauth2 = new WechatOauth2();
        $config       = $this->getPlugin()->getConfig();
        $wechatOauth2->setAppKey($config['app_id']);
        $wechatOauth2->setAppSecret($config['app_secret']);
        //var_dump("appid");
        //var_dump($config['app_id']);
        //var_dump("app_secret");
        //var_dump($config['app_secret']);
        $token = null;
        try {
            $token = $wechatOauth2->getAccessToken($code);
        } catch (\Exception $e) {
            $this->error('登录失败1！' . $e->getMessage(), '/');
        }
        //var_dump($token);
        //获取当前登录用户信息
        if (!is_array($token)) {
            $this->success('登录失败1！', '/plugin/xiongyi/index/login');
        }

        $data = $wechatOauth2->call('sns/userinfo');
        //var_dump($data);
        /**
         * array(10) { 
         * ["openid"]=> string(28) "ocs7O67mv5obM2xjY0F3Xzv26XtA" 
         * ["nickname"]=> string(12) "夕阳余晖" 
         * ["sex"]=> int(0) ["language"]=> string(0) "" 
         * ["city"]=> string(0) "" 
         * ["province"]=> string(0) "" 
         * ["country"]=> string(0) "" 
         * ["headimgurl"]=> string(152) "https://thirdwx.qlogo.cn/mmopen/vi_32/D9hhtg7QVjfHAgRvdk59TfbscOXEVgkQu1v4reLZpE3JQEcq2DbPJqyiakjd8a7R4w2fShAFNBkDzL6qYMxWpF5L15Y4ia7MT5pDV1eEqeMiag/132" 
         * ["privilege"]=> array(0) { } 
         * ["unionid"]=> string(28) "opKXO61L5ZYgdvwEoOiw35bCIYCs" }    ////同一个开放平台添加的web页和小程序，获得的unionid是一样的
         */

        $userInfo = [
            'app_id'    => $config['app_id'],   //将APP_ID也传给写入到third_party_user表，以防后面多个应用接入使用
            'third_party' => 'wechat',
            'nickname'    => $data['nickname'],
            'avatar'      => $data['headimgurl'],
            'union_id'    => $data['unionid'],          //新增，用于微信WEB页登录 与 微信小程序登录 识别同一个用户
        ];
        $newUserData = [
            //user表数据
            'user_nickname'   => $userInfo['nickname'],
            'avatar'          => $userInfo['avatar'],
            'last_login_time' => time(),
            'last_login_ip'   => get_client_ip(0, true),
            'create_time'     => time(),
            'user_status'     => '1',
            "user_type"       => '1',   //1-admin，2-会员
            //third_party_user表数据
            'expire_time'     => intval(time() + $token['expires_in']), //access_token过期时间
            'nickname'        => $userInfo['nickname'],
            'third_party'     => 'wechat',
            'access_token'    => $token['access_token'],        //access_token过期时间
            'openid'          => $token['openid'],
            'app_id'        =>  $userInfo['app_id'],
            'union_id'         => $userInfo['union_id'],     //WEB和小程序绑定开放平台后，同一个微信用户union_id是一样的
        ];

        $sessionOauthBang = session('oauth_bang');

        //$findThirdPartyUser = Db::name('third_party_user')->where(["third_party" => $type, "openid" => $token['openid']])->find();
        //不使用openid，因为同一个开放平台要兼容微信web登录和小程序登录，使用unionid识别即可
        $findThirdPartyUser = Db::name('third_party_user')->where(["union_id" => $userInfo['union_id']])->find();
        $needRegister       = true;
        if ($findThirdPartyUser) {
            $findUser = Db::name('user')->where(["id" => $findThirdPartyUser['user_id']])->find();
            if ($findUser) {
                $needRegister = false;
                if ($findUser['user_status'] != '1') {
                    $this->error('帐号还未启用，请联系网站管理员！即将返回首页。', '/');
                }

                if (!empty($findUser['more'])) $findUser['more'] = json_decode($findUser['more'], true);

                //判断用户是否有role和zzjg
                //$ups = new UserPublicService;
                $ups = new User();
                $b = $ups->checkUserRoleAndZzjg($findUser['id']);
                if ($b) {
                    //session('user', $findUser); //user是前台用户的     
                    //$this->success("登陆成功", $this->_getLoginRedirect());

                    /** 修改成后台用户登陆 , 为了让api能使用微信登录后的restAdminController，START*/
                    //写入后台管理员session
                    session('ADMIN_ID', $findUser["id"]);
                    session('name', $findUser["user_login"]);
                    $data                    = [];
                    $data['last_login_ip']   = get_client_ip(0, true);
                    $data['last_login_time'] = time();
                    $token                   = cmf_generate_user_token($findUser["id"], $userInfo['third_party']);
                    if (!empty($token)) {
                        session('token', $token);
                    }
                    Db::name('user')->where('id', $findUser['id'])->update($data);
                    cookie("admin_username", $findUser["user_login"], 3600 * 24 * 30);
                    session("__LOGIN_BY_CMF_ADMIN_PW__", null);
                    /**修改成后台用户登陆 END*/
                    //$this->success("登陆成功", $this->_getLoginRedirect());

                    //必须在前端页面里将token和deviceType保存到localstroe内，
                    //然后js在post调用api的时候在header里添加token和x-device-type,
                    //否则restbasecontroller在调用_initUser()方法时，会判断的header内参数为空
                    $this->assign('url', '/admin/index/index');
                    $this->assign('wait', 3);
                    $this->assign('token', $token);
                    $this->assign('LoginDeviceType', $userInfo['third_party']);
                    $this->assign('user', $findUser);
                    return $this->fetch('/redirect');       //在这个页面里将token保存到localstore，然后让post接口程序的js拿到token
                    
                    /*$this->redirect("/plugin/xiongyi/wechat/wechatloginredirect",302, ['token' => $token, 'user' => [
                        'id'            => $user['id'],
                        'user_login'    => $user['user_login'],
                        'user_nickname' => $user['user_nickname'],
                    ]]);*/


                } else {
                    //此用户没有绑定角色和组织机构
                    $this->assign('userInfo', $newUserData);
                    $this->assign('user_id', $findUser['id']);
                    $this->assign('title', '微信登录用户绑定角色和组织机构');
                    return $this->fetch('index/userbind');
                }
            } else {
                $needRegister = true;
            }
        }

        if ($needRegister) {
            //此用户没有注册过
            $this->assign('userInfo', $newUserData);
            $this->assign('title', '微信登录用户注册');
            return $this->fetch('index/userreg');
        }
    }

    /**
     * 获取登录跳转地址
     */
    private function _getLoginRedirect()
    {
        $sessionLoginHttpReferer = session('login_http_referer');
        //return empty($sessionLoginHttpReferer) ? cmf_get_root() . "/admin" : $sessionLoginHttpReferer;
        return "/admin/index/index";
    }

    /**
     * 登陆成功后写入session
     * $third_party，第三方类型：mobile,android,iphone,ipad,web,pc,mac,wxapp
     */
    private function _pSession($user, $third_party)
    {
        /**修改成后台用户登陆 START*/
        session('ADMIN_ID', $user["id"]);
        session('name', $user["user_login"]);
        $data                    = [];
        $data['last_login_ip']   = get_client_ip(0, true);
        $data['last_login_time'] = time();
        $token                   = cmf_generate_user_token($user["id"], $third_party);
        if (!empty($token)) {
            session('token', $token);
        }
        Db::name('user')->where('id', $user['id'])->update($data);
        cookie("admin_username", $user["user_login"], 3600 * 24 * 30);
        session("__LOGIN_BY_CMF_ADMIN_PW__", null);

        /*$this->redirect("/plugin/xiongyi/wechat/wechatloginredirect",302, ['token' => $token, 'user' => [
            'id'            => $user['id'],
            'user_login'    => $user['user_login'],
            'user_nickname' => $user['user_nickname'],
        ]]);*/

        /**修改成后台用户登陆 END*/
    }

    /**
     * 页面跳转
     */
    public function wechatloginredirect()
    {
        $user['token'] = 'abcd';
        $this->assign('url', '/admin/index/index');
        $this->assign('wait', 3);
        $this->assign('token', $user['token']);
        return $this->fetch('/redirect');
    }

        /**
     * 发送GET请求
     *
     * @param string $url 请求的URL
     * @param array $params URL参数
     * @param array $headers 请求头
     * @return mixed
     */
    public static function get($url, $params = [], $headers = [])
    {
        $ch = curl_init();
        if (!empty($params)) {
            $url .= '?' . http_build_query($params);
        }
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        $output = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            //Log::error('HTTP GET Request Error: ' . $error);
            throw new HttpException(500, 'HTTP GET Request Error: ' . $error);
        }

        return json_decode($output, true);
    }

    /**
     * 发送POST请求
     *
     * @param string $url 请求的URL
     * @param array $data POST数据
     * @param array $headers 请求头
     * @return mixed
     */
    public static function post($url, $data = [], $headers = [])
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
        if (!empty($headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        $output = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            //Log::error('HTTP POST Request Error: ' . $error);
            throw new HttpException(500, 'HTTP POST Request Error: ' . $error);
        }

        return json_decode($output, true);
    }
}
